package service

import (
	"context"
	"net/http"

	"github.com/go-kratos/kratos/v2/log"

	pb "gitee.com/danqingzhao/go-dango/api/user/permission/v1"
	"gitee.com/danqingzhao/go-dango/apps/user/biz"
	"gitee.com/danqingzhao/go-dango/pkg/common/core"
	"gitee.com/danqingzhao/go-dango/pkg/proto/settings"
)

type PermissionService struct {
	pb.UnimplementedPermissionServer
	log    *log.Helper
	ucPerm *biz.PermissionUsecase
}

func NewPermissionService(uc *biz.PermissionUsecase, logHelpers *settings.LogHelpers) *PermissionService {
	return &PermissionService{ucPerm: uc, log: logHelpers.Server}
}

func (s *PermissionService) CreatePermission(
	ctx context.Context,
	req *pb.CreatePermissionRequest,
) (*pb.PermissionReply, error) {
	im := biz.PermissionModel{
		GrpcUrl:  req.GrpcUrl,
		HttpUrl:  req.HttpUrl,
		Method:   int32(req.Method),
		AppName:  req.AppName,
		IsActive: req.IsActive,
		Descr:    req.Descr,
	}
	om, err := s.ucPerm.CreatePermission(ctx, im)
	if err != nil {
		return nil, err
	}
	data := PermissionSchemasOutBase(ctx, s.log, *om)
	return &pb.PermissionReply{Code: http.StatusCreated, Message: "", Metadata: data}, nil
}

func (s *PermissionService) UpdatePermission(
	ctx context.Context,
	req *pb.UpdatePermissionRequest,
) (*pb.PermissionReply, error) {
	im := biz.PermissionModel{
		Id:       req.Pk,
		GrpcUrl:  req.GrpcUrl,
		HttpUrl:  req.HttpUrl,
		Method:   int32(req.Method),
		AppName:  req.AppName,
		IsActive: req.IsActive,
		Descr:    req.Descr,
	}
	om, err := s.ucPerm.UpdatePermissionById(ctx, req.Pk, im)
	if err != nil {
		return nil, err
	}
	data := PermissionSchemasOutBase(ctx, s.log, *om)
	return &pb.PermissionReply{Code: http.StatusOK, Message: "", Metadata: data}, nil
}

func (s *PermissionService) DeletePermission(
	ctx context.Context,
	req *pb.DeletePermissionRequest,
) (*pb.PermissionReply, error) {
	if err := s.ucPerm.DeletePermissionById(ctx, req.Pk); err != nil {
		return nil, err
	}
	return &pb.PermissionReply{Code: http.StatusOK, Message: "", Metadata: nil}, nil
}

func (s *PermissionService) GetPermission(
	ctx context.Context,
	req *pb.GetPermissionRequest,
) (*pb.PermissionReply, error) {
	om, err := s.ucPerm.FindPermissionById(ctx, req.Pk)
	if err != nil {
		return nil, err
	}
	data := PermissionSchemasOutBase(ctx, s.log, *om)
	return &pb.PermissionReply{Code: http.StatusOK, Message: "", Metadata: data}, nil
}

func (s *PermissionService) ListPermission(
	ctx context.Context,
	req *pb.ListPermissionRequest,
) (*pb.PagPermissionReply, error) {
	page, size, query := s.filterMenu(req)
	count, ms, err := s.ucPerm.ListPermission(ctx, page, size, query)
	if err != nil {
		return nil, err
	}
	mso := ListPermissionModelToSchemasOutBase(ctx, s.log, ms)
	rsp := pb.PagPermissionOutBase{
		Items: mso,
		Page:  int64(page),
		Pages: core.CountPages(count, int64(size)),
		Size:  int64(size),
		Total: count,
	}
	return &pb.PagPermissionReply{Code: http.StatusOK, Message: "", Metadata: &rsp}, nil
}

func (s *PermissionService) filterMenu(
	req *pb.ListPermissionRequest,
) (int, int, map[string]any) {
	var (
		page  int            = core.DefaultPage
		size  int            = core.DefaultSize
		query map[string]any = make(map[string]any)
	)
	if req != nil {
		if req.Page > 0 {
			page = int(req.Page)
		}
		if req.Size > 0 {
			size = int(req.Size)
		}
		if req.Pk != 0 {
			query["id = ?"] = req.Pk
		} else if req.Pks != "" {
			pks := core.StringToListUint32(req.Pks)
			if len(pks) > 1 {
				query["id in ?"] = pks
			}
		}
		if req.GrpcUrl != "" {
			query["grpc_url like ?"] = req.GrpcUrl
		}
		if req.HttpUrl != "" {
			query["http_url like ?"] = req.HttpUrl
		}
		if req.Method != pb.MethodEnum_UNKNOW {
			query["method = ?"] = pb.MethodEnum_name[int32(req.Method)]
		}
		if req.AppName != "" {
			query["app_name = ?"] = req.AppName
		}
		if req.IsActive != nil {
			query["is_active = ?"] = req.IsActive
		}
	}
	return page, size, query
}

func PermissionSchemasOutBase(
	ctx context.Context,
	logHelper *log.Helper,
	m biz.PermissionModel,
) *pb.PermissionOutBase {
	return &pb.PermissionOutBase{
		Id:          m.Id,
		CreatedTime: m.CreatedAt.String(),
		UpdatedTime: m.UpdatedAt.String(),
		GrpcUrl:     m.GrpcUrl,
		HttpUrl:     m.HttpUrl,
		Method:      pb.MethodEnum(m.Method),
		IsActive:    m.IsActive,
		Descr:       m.Descr,
	}
}

func ListPermissionModelToSchemasOutBase(
	ctx context.Context,
	logHelper *log.Helper,
	ms []biz.PermissionModel,
) []*pb.PermissionOutBase {
	mso := make([]*pb.PermissionOutBase, 0, len(ms))
	if len(ms) > 0 {
		for _, m := range ms {
			mo := PermissionSchemasOutBase(ctx, logHelper, m)
			mso = append(mso, mo)
		}
	}
	return mso
}
